﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Threading;
using System.ComponentModel;
using System.Net;
using Aggregation_Clustering;
using System.IO;
using Microsoft.Win32;
using System.Collections;
using System.Windows.Forms;
using Visifire.Charts;

namespace WpfAlgorithm1
{
    /// <summary>
    /// MainWindow.xaml 的交互逻辑
    /// </summary>
    public partial class MainWindow : Window
    {
        public string filepath;
        public string outputpath;
        public string filename;
        public int LBound,UBound;
        public double a1, a2;
        private bool ifnormalization;

        public BackgroundWorker bgw;
        DateTime timestart;
        string TimeStamp;
        string timeusing;
        ClusterList clusterlist;

        bool ifPoints;
        Point[] points;

        public MainWindow()
        {
            InitializeComponent();
            bgw = new BackgroundWorker();
            bgw.WorkerReportsProgress = true;
            bgw.ProgressChanged += bgw_ProgressChanged;
            bgw.RunWorkerCompleted += bgw_RunWorkerCompleted;
            bgw.DoWork += bgw_DoWork;
        }

        private void button1_Click(object sender, RoutedEventArgs e)
        {
            Microsoft.Win32.OpenFileDialog openFileDialog1 = new Microsoft.Win32.OpenFileDialog();
            //openFileDialog1.Filter = "文档(*.in)|*.in";
            //openFileDialog1.Filter = "所有文件(*.*)|*.*";
            openFileDialog1.Filter = "file(*.*)|*.in;*.txt";
            if (openFileDialog1.ShowDialog() == true)
            {
                if (openFileDialog1.FileName != "")
                {
                    filepath = openFileDialog1.FileName;
                    //outputpath=openFileDialog1
                    this.textBox1.Text = filepath;
                    string[] temp = filepath.Split('\\');
                    string outputpath = temp[0];
                    for (int i = 1; i < temp.Length - 1; i++)
                    {
                        outputpath += "\\" + temp[i];
                    }
                    this.textBox2.Text = outputpath;
                    //string[] filepathname = filepath.Split('\\','.');
                    //for (int i = 0; i < filepathname.Count(); i++)
                    //{
                    //    if (filepathname[i] == "txt" || filepathname[i] == "in")
                    //    {
                    //        filename = filepathname[i - 1];
                    //    }
                    //}
                }
            }
        }
        private void button3_Click(object sender, RoutedEventArgs e)
        {
            FolderBrowserDialog openFolderDlg = new FolderBrowserDialog();
            if (this.textBox2.Text != "")
            {
                openFolderDlg.SelectedPath = this.textBox2.Text;
            }
            openFolderDlg.ShowDialog();
            if (openFolderDlg.SelectedPath != string.Empty)
                outputpath = openFolderDlg.SelectedPath;
            this.textBox2.Text = outputpath;
        }

        private void button2_Click(object sender, RoutedEventArgs e)
        {
            outputpath = this.textBox2.Text;
            #region Confirm the format
            if (textBox1.Text == "" || textBox2.Text == "" || textBox3.Text == "" || textBox4.Text == "" || tb_a1.Text == "" || tb_a2.Text == "")
       
            {
                System.Windows.MessageBox.Show("Please complete input!");
                return;
            }

            try
            {
                LBound = Convert.ToInt32(this.textBox3.Text);
                UBound = Convert.ToInt32(this.textBox4.Text);
                a1 = Convert.ToDouble(this.tb_a1.Text);
                a2 = Convert.ToDouble(this.tb_a2.Text);
            }
            catch (Exception)
            {
                System.Windows.MessageBox.Show("Input string was not in a correct format.");
                return;
            }

            if (LBound > UBound)
            {
                System.Windows.MessageBox.Show("UBound is smaller than LBound!");
                return;
            }

            if (a1 > 1 || a1 <= 0 || a2 > 1 || a2 < 0)
            {
                System.Windows.MessageBox.Show("The weight of Average： a1 ∈ (0,1]\nThe weight of Variance： a2 ∈ [0,1]");
                return;
            }
            #endregion




            //显示当前时间
            string[] time1 = { "", "", "", "", "", "" };
            DateTime time2 = System.DateTime.Now;
            time1[0] = time2.Year.ToString();
            time1[1] = time2.Month.ToString();
            time1[2] = time2.Day.ToString();
            time1[3] = time2.Hour.ToString();
            time1[4] = time2.Minute.ToString();
            time1[5] = time2.Second.ToString();
            for (int i = 1; i < 6; i++)
            {
                if (Convert.ToInt32(time1[i]) < 10) time1[i] = "0" + time1[i];
            }
            /*string[] time1 = time.Split(' ','/',':');
            if (Convert.ToInt32(time1[1]) < 10)
            {
                time1[1] = "0" + time1[1];
            }*/
            TimeStamp = time1[0] + time1[1] + time1[2] + time1[3] + time1[4] + time1[5];
            timestart = System.DateTime.Now;

            ifnormalization = cb_nor.IsChecked.Value;

            bgw.RunWorkerAsync();
            this.button2.IsEnabled = false;
           
        }

        private void bgw_DoWork(object sender, DoWorkEventArgs e)
        {
            BackgroundWorker bk = sender as BackgroundWorker;

            clusterlist = new ClusterList();
            StreamReader sr = new StreamReader(filepath);
            string line, FileName;
            int ElementNum, ClusterNum;
            try
            {

                FileName = sr.ReadLine();
                string[] filepathname = FileName.Split('.');
                filename = filepathname[0];
                if (filename.Contains("TP"))
                {
                    ifPoints = true;
                }else{
                    ifPoints = false;
                }
                line = sr.ReadLine();
                string[] information = line.Split(' ');
                // reject the duplicate ' '
                int i = 0;
                while (information[i] == "")
                {
                    i++;
                }
                ElementNum = Convert.ToInt32(information[i]);
                i++;
                while (information[i] == "")
                {
                    i++;
                }
                ClusterNum = Convert.ToInt32(information[i]);
            }
            catch (Exception)
            {

                throw;
            }

            points = new Point[ElementNum];
            double[,] inputScore = new double[ElementNum + 1, ElementNum + 1];
            bk.ReportProgress(10, "Loading Elements & Scores...");
            for (int i = 0; i < ElementNum; i++)
            {
                clusterlist.AddElement2defaultCluster(new Element());
            }

            if (!ifPoints)
            {
                while (!(line = sr.ReadLine()).Contains("-999"))
                {
                    string[] sarray = line.Split(' ');
                    int temp = sarray.Count();
                    int x = 0, y = 0, value = 0;
                    int count = 0;
                    for (int i = 0; i < temp; i++)
                    {
                        if (sarray[i] != "" && count == 0)
                        {
                            x = Convert.ToInt32(sarray[i]);
                            count++;
                        }
                        else if (sarray[i] != "" && count == 1)
                        {
                            y = Convert.ToInt32(sarray[i]);
                            count++;
                        }
                        else if (sarray[i] != "" && count == 2)
                        {
                            value = Convert.ToInt32(sarray[i]);
                            count++;
                        }
                    }
                    if (value > 0)
                    {
                        inputScore[x, y] = value;
                        inputScore[y, x] = value;
                    }
                    else
                    {
                        inputScore[x, y] = -value;
                        inputScore[y, x] = -value;
                    }
                }
            }
            else//输入参数为点集
            {
                try
                {
                    while (!(line = sr.ReadLine()).Contains("-999"))
                    {
                        string[] str_temp = line.Split('(');
                        int number = int.Parse(str_temp[0]);
                        str_temp = str_temp[1].Split(')');
                        str_temp = str_temp[0].Split(',');

                        points[number - 1].X = double.Parse(str_temp[0]);
                        points[number - 1].Y = double.Parse(str_temp[1]);
                    }
                    for (int i = 1; i <= ElementNum; i++)
                    {
                        for (int j = 1; j <= ElementNum; j++)
                        {
                            inputScore[i, j] = MathHelper.Distance(points[i - 1], points[j - 1]);
                        }
                    }
                }
                catch (Exception ex)
                {
                    System.Windows.MessageBox.Show(ex.ToString());                    
                }
            }



            clusterlist.ImportScore(inputScore,ifnormalization,ElementNum);
            
            clusterlist.InitClusters(ClusterNum, UBound, LBound, a1, a2);
            if (sr != null) sr.Close();




            try
            {
                bk.ReportProgress(30, "Initializing the initial solution..."); Thread.Sleep(500);
                clusterlist.Create2EleClusters();
                clusterlist.InitTSPhase();
                bk.ReportProgress(40, "Executing TS...");
                clusterlist.ExecTSPhase();

                ArrayList arr = clusterlist.GetMoveLogList();
                bk.ReportProgress(85, "Writing LogFile..."); Thread.Sleep(500);
                FileStream cFile = new FileStream(outputpath + "\\log_" + filename + "_" + TimeStamp + ".txt", FileMode.OpenOrCreate);
                using (StreamWriter sw = new StreamWriter(cFile))
                {
                    for (int i = 0; i < arr.Count; i++)
                    {
                        sw.WriteLine(arr[i].ToString());
                    }
                }
            }
            catch (Exception exc)
            {

                FileStream cFile = new FileStream(outputpath + "\\log_" + filename + "_" + TimeStamp + ".txt", FileMode.OpenOrCreate);
                using (StreamWriter sw = new StreamWriter(cFile))
                {
                    sw.WriteLine(exc.Message + "\r\n");
                }
            }





            //计算并显示运算使用时间
            string time = System.DateTime.Now.ToString();
            TimeSpan ts1 = new TimeSpan(timestart.Ticks);
            TimeSpan ts2 = new TimeSpan(System.DateTime.Now.Ticks);
            TimeSpan ts = ts1.Subtract(ts2).Duration();
            string sthours, stminutes, stseconds, stmseconds;
            int ihours = Convert.ToInt32(ts.Hours);
            int iminutes = Convert.ToInt32(ts.Minutes);
            int iseconds = Convert.ToInt32(ts.Seconds);
            int imseconds = Convert.ToInt32(ts.Milliseconds);
            if (ihours < 10)
            {
                sthours = "0" + ts.Hours.ToString();
            }
            else
            {
                sthours = ts.Hours.ToString();
            }
            if (iminutes < 10)
            {
                stminutes = "0" + ts.Minutes.ToString();
            }
            else
            {
                stminutes = ts.Minutes.ToString();
            }
            if (iseconds < 10)
            {
                stseconds = "0" + ts.Seconds.ToString();
            }
            else
            {
                stseconds = ts.Seconds.ToString();
            }
            if (imseconds < 10)
            {
                stmseconds = "0" + ts.Milliseconds.ToString();
            }
            else
            {
                stmseconds = ts.Milliseconds.ToString();
            }
            timeusing = sthours + ":"
                    + stminutes + ":"
                    + stseconds + ":"
                    + stmseconds;


            bk.ReportProgress(90, "Writing ClusterFile..."); Thread.Sleep(500);
            //输出三个文件
            FileStream aFile = new FileStream(outputpath + "\\cluster_" + filename + "_" + TimeStamp + ".txt", FileMode.OpenOrCreate);
            try
            {
                ArrayList arr = clusterlist.GetClusterLogList();
                using (StreamWriter sw = new StreamWriter(aFile))
                {
                    for (int i = 0; i < arr.Count; i++)
                    {
                        sw.WriteLine(arr[i].ToString());
                    }
                }
            }
            catch (Exception exc)
            {
                using (StreamWriter sw = new StreamWriter(aFile))
                {
                    sw.WriteLine(exc.Message + "\r\n");
                }
            }

            bk.ReportProgress(95, "Writing ElementFile...");
            Thread.Sleep(500);
            FileStream bFile = new FileStream(outputpath + "\\element_" + filename + "_" + TimeStamp + ".txt", FileMode.OpenOrCreate);
            using (StreamWriter sw = new StreamWriter(bFile))
            {
                sw.WriteLine("CID\t EID\t X\t Y\t" + '\n');
                //for (int i = 1; i <= ElementNum; i++)
                //{
                //        sw.WriteLine(clusterlist.getElementbyID(i).ElementID.ToString() + " ," + clusterlist.getElementbyID(i).ClusterID.ToString() + '\n');
                //}
                if (ifPoints)
                {
                    for (int i = 1; i <= ClusterNum; i++)
                    {
                        for (int j = 1; j <= ElementNum; j++)
                        {
                            if (clusterlist.getElementbyID(j).ClusterID == i)
                            {
                                int eleid = clusterlist.getElementbyID(j).ElementID;
                                sw.WriteLine(clusterlist.getElementbyID(j).ClusterID.ToString() + "\t" + eleid + "\t"+points[eleid-1].X.ToString("0.0")+"\t"+points[eleid-1].Y.ToString("0.0") + '\n');
                            }
                        }
                    }
                }
                else//非点集的输出
                {
                    for (int i = 1; i <= ClusterNum; i++)
                    {
                        for (int j = 1; j <= ElementNum; j++)
                        {
                            if (clusterlist.getElementbyID(j).ClusterID == i)
                            {
                                int eleid = clusterlist.getElementbyID(j).ElementID;
                                sw.WriteLine(clusterlist.getElementbyID(j).ClusterID.ToString() + "\t" + eleid + "\t-1\t-1" + '\n');
                            }
                        }
                    }
                }
            }

            //cluster文件:cluster的编号, 总的对象个数, 实际的总容量
            //第一行是文件名
            //第二行是需要cluster的元素的个数, 可用的clutser的数目,
            //和惩罚值 (我不是很清楚这事什么,Fred的文章中似乎没有提到, 我还在问)
            //第三行开始是相应的数据, 是一个点到另外一个点的权重或是距离
            //最后一行-999标明结束

        }
        private void bgw_ProgressChanged(object sender, ProgressChangedEventArgs e)
        {
            this.pb_1.Value = e.ProgressPercentage;
            this.tb_progress.Text = e.UserState.ToString();
        }
        private void bgw_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            this.pb_1.Value = 100;
            this.tb_progress.Text = "Done!";
            this.button2.IsEnabled = true;
            System.Windows.MessageBox.Show("Computational Time:  " + timeusing);

            //show the line chart
            if(clusterlist!=null)
            {
                ArrayList values1 = clusterlist.GetObjValList();
                ArrayList values2 = clusterlist.GetObj_Vari_ValList();
                if(values1!=null&&values2!=null){
                    ChartHelper ch = new ChartHelper();
                    ChartInformation ci = new ChartInformation();
                    ci.ImportLineData(values1,values2);
                    Chart m_chart = ch.CreateChart(ci);
                    WindowResultLineChart m_window = new WindowResultLineChart(m_chart);
                    m_window.Show();

                    //this.Dispatcher.BeginInvoke(new Action(() =>
                    //{
                    //    int Height = (int)m_chart.ActualHeight;
                    //    int Width = (int)m_chart.ActualWidth;
                    //    RenderTargetBitmap bmp = new RenderTargetBitmap(Width, Height, 96, 96, PixelFormats.Pbgra32);
                    //    bmp.Render(m_chart);
                    //    string file = outputpath+"\\a.jpg";
                    //    BitmapEncoder encoder;
                    //    encoder = new JpegBitmapEncoder();
                    //    encoder.Frames.Add(BitmapFrame.Create(bmp));
                    //    using (Stream stm = File.Create(file))
                    //    {
                    //        encoder.Save(stm);
                    //    }
                    //}), System.Windows.Threading.DispatcherPriority.Render);
                }
            }
        }
    }
}
